import threading
from client import BaiduClient
import utils
import pickle
import global_
import conf
import logging
import time


class StoppableThread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self):
        super(StoppableThread, self).__init__()
        self._stop_event = threading.Event()

    def stop(self):
        self._stop_event.set()

    @property
    def stopped(self):
        return self._stop_event.is_set()


class MyThread(StoppableThread):

    def __init__(self, ak):
        super(MyThread, self).__init__()
        self.ak = ak

    def run(self):
        client = BaiduClient(self.ak, 'data/sh', self._stop_event)
        client.download()


def save():
    print('saving...')
    with open('data/to_download.pkl', 'wb') as f:
        to_download = utils.queue2list(global_.to_download_queue)
        pickle.dump(to_download, f)
    with open('data/downloaded.pkl', 'wb') as f:
        downloaded = utils.queue2list(global_.downloaded_queue)
        pickle.dump(downloaded, f)
    print("saved")


class SaveThread(StoppableThread):

    def run(self):
        s = 0
        while True:
            time.sleep(1)
            s += 1
            if self.stopped:
                print('save thread exiting...')
                break
            if s % (60 * 5) == 0:
                global_.lock.acquire()
                save()
                global_.lock.release()


def main():
    with open('data/to_download.pkl', 'rb') as f:
        to_download = pickle.load(f)
    with open('data/downloaded.pkl', 'rb') as f:
        downloaded = pickle.load(f)
    global_.to_download_queue = utils.list2queue(to_download)
    global_.downloaded_queue = utils.list2queue(downloaded)
    global_.lock = threading.Lock()

    threads = []
    for ak in conf.aks:
        for i in range(1):
            thread = MyThread(ak)
            thread.start()
            threads.append(thread)
    save_thread = SaveThread()
    save_thread.start()
    try:
        for thread in threads:
            thread.join()
    except KeyboardInterrupt:
        print('Please wait for threads to exit gracefully! DON\'T PRESS CTRL+C!!')
    finally:
        for thread in threads:
            thread.stop()
        for thread in threads:
            thread.join()
        save_thread.stop()
        save_thread.join()
    print('OK.')


if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    main()
